// (C) 2022 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

`include "mainfpga_version.vh"

module perst
(
    input       iClk,
    input       iRst_n,

    input       iPWRGD_CPU,                         // From master_fub, indicate CPU power good
    input       iPLTRST_N,                          // From CPU after PFR filtering, indicate to the platform to reset platform functions
    input       iFM_RST_PERST_BIT,                  // From on-board jumper, choose PERST follow which signal
    input       FM_PERST_TIMING_SEL,                // From on-board jumper J8A9, choose delay timing parameter
    input       iRST_CPU_RESET_R_N,                 // To follow CPU_RESET

    output      oRST_PLD_PCIE_CPU_DEV_PERST_R_N     // To PCIe divices, trigger to reset PCIe devices

);

/*************************************************************************************************************
 * Local Parameter Definitions                                                                               *
 *************************************************************************************************************/
    localparam LOW  = 1'b0;
    localparam HIGH = 1'b1;

   `ifdef SIMULATION
        localparam T_100mS_2M  = 9'd200;
        localparam T_1S_2M     = 11'd1000;
   `else
        localparam T_100mS_2M  = 19'd200000;
        localparam T_1S_2M     = 21'd2000000;
   `endif

   wire    wDoneTimer100ms;
   wire    wDoneTimer1s;
   wire    PWRGD_Timer_Done;

/*************************************************************************************************************
 * Local Registers and Wires Definitions                                                                     *
 *************************************************************************************************************/
   assign PWRGD_Timer_Done = (wDoneTimer100ms || wDoneTimer1s) && iPWRGD_CPU;   // High means CPU PWRGD is asserted and timer done

/*************************************************************************************************************
 * Logic                                                                                                     *
 *************************************************************************************************************/  
    
	
	assign oRST_PLD_PCIE_CPU_DEV_PERST_R_N = iFM_RST_PERST_BIT ? iRST_CPU_RESET_R_N : (iPWRGD_CPU && PWRGD_Timer_Done) ;
	

/*************************************************************************************************************
 * Instances                                                                                                 *
 *************************************************************************************************************/
    // T?: min 100 ms timer, for PCIe compatible check. From CPU PWRGD assertion to PERST# de-assertion
    delay #(.COUNT(T_100mS_2M)) 
        Timer100ms (
            .iClk    ( iClk                              ),
            .iRst    ( iRst_n                            ),
            .iStart  ( iPWRGD_CPU && FM_PERST_TIMING_SEL ),
            .iClrCnt ( 1'b0                              ),
            .oDone   ( wDoneTimer100ms                   )
        );

    // T?: min 1 s timer, for to support OCP NIC 3.0. From CPU PWRGD assertion to PERST# de-assertion
    delay #(.COUNT(T_1S_2M)) 
        Timer1s (
            .iClk    ( iClk                               ),
            .iRst    ( iRst_n                             ),
            .iStart  ( iPWRGD_CPU && ~FM_PERST_TIMING_SEL ),
            .iClrCnt ( 1'b0                               ),
            .oDone   ( wDoneTimer1s                       )
        );

endmodule
